package com.kexin.common.utils;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Random;
import java.util.TimeZone;

import org.apache.commons.lang.StringUtils;

import java.text.SimpleDateFormat;
import java.text.ParseException;

/**
 * 时间工具类
 * 
 * @author AoCongKui
 */
public class DateUtil {

	public static final TimeZone timeZone = TimeZone.getTimeZone("GMT+8");

	//年月日时分秒（无下划线） yyyyMMddHHmmss
	public static final String dtLong = "yyyyMMddHHmmss";

	//年月日时分（无下划线） yyyyMMddHHmm
	public static final String dmLong = "yyyyMMddHHmm";

	//年月日时分秒毫秒（无下划线） yyyyMMddHHmmssSSS
	public static final String dtsLong = "yyyyMMddHHmmssSSS";

	//完整时间（精确到秒，有下划线） yyyy-MM-dd HH:mm:ss
	public static final String simple = "yyyy-MM-dd HH:mm:ss";

	//完整时间 （精确到毫秒，有下划线） yyyy-MM-dd HH:mm:ss.SSS
	public static final String simpleDate = "yyyy-MM-dd HH:mm:ss.SSS";

	//年月日（无下划线） yyyyMMdd
	public static final String dtShort = "yyyyMMdd";

	//年月日（有下划线） yyyy-MM-dd
	public static final String dtShorts = "yyyy-MM-dd";

	//时间表达式 "ss mm HH dd MM ? yyyy"
	public static final String cronDate = "ss mm HH dd MM ? yyyy";

	/**
	 * 返回系统当前时间（精确到秒），作为一个唯一的编号
	 * 
	 * @return 以yyyyMMddHHmmss为格式的当前系统时间字符串
	 */
	public static String getTimeNo() {
		return getTimeNo(new Date());
	}

	/**
	 * 返回指定时间（精确到秒），作为一个唯一的编号
	 * @param date 时间对象
	 * @return 以yyyyMMddHHmmss为格式的指定时间字符串
	 */
	public static String getTimeNo(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dtLong);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 返回系统当前时间（精确到毫秒），作为一个唯一的编号
	 * 
	 * @return 以yyyyMMddHHmmssSSS为格式的当前系统时间字符串
	 */
	public static String getTimeNumber() {
		return getTimeNumber(new Date());
	}

	/**
	 * 返回指定时间（精确到毫秒），作为一个唯一的编号
	 * @param date 时间对象
	 * @return 以yyyyMMddHHmmssSSS为格式的指定时间字符串
	 */
	public static String getTimeNumber(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dtsLong);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 获取系统当前日期（精确到毫秒），格式：yyyy-MM-dd HH:mm:ss.SSS
	 * 
	 * @return 以yyyyMMddHHmmssSSS为格式的当前系统时间为格式的当前系统时间字符串
	 */
	public static String getDateFormatterString() {
		return getDateFormatterString(new Date());
	}

	/**
	 * 获取指定时间（精确到毫秒），格式：yyyy-MM-dd HH:mm:ss.SSS
	 * @param date 时间对象
	 * @return 以yyyyMMddHHmmssSSS为格式的当前系统时间为格式的指定时间字符串
	 */
	public static String getDateFormatterString(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(simpleDate);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 获取时间字符串
	 * 后天为“后天HH:mm”，明天为“明天HH:mm”，今天为“HH:mm”，前天为“昨天HH:mm”，前天为“前天HH:mm”
	 * @param date 时间对象
	 * @return
	 */
	public static String getDateString(Date date) {
		return getDateString(date, false);
	}

	/**
	 * 获取时间字符串
	 * 后天为“后天HH:mm”，明天为“明天HH:mm”，今天为“HH:mm”，
	 * 前天为“昨天HH:mm”，前天为“前天HH:mm”，三天前为“三天前HH:mm”，
	 * 四天前为“四天前HH:mm”，五天前为“五天前HH:mm”，六天前为“六天前HH:mm”，
	 * 一周前至今年内为“MM月dd日 HH:mm”或“MM月dd日”，
	 * 去年及之前为“yyyy年MM月dd日 HH:mm”或“yyyy年MM月dd日”
	 * @param date 时间对象
	 * @param isOtherTime 其他是否显示时间
	 * @return
	 */
	public static String getDateString(Date date, boolean isOtherTime) {
		if (date==null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance(timeZone);
		Date nowDate = setEndDate(calendar.getTime());
		if (date.getTime()>nowDate.getTime()) {
			nowDate = setStartDate(calendar.getTime());
		}
		
		//拿到当前年份
		int nowYear = calendar.get(Calendar.YEAR);
		
		calendar.setTime(date);
		//拿到传入时间的年份
		int year = calendar.get(Calendar.YEAR);
		
		//拿到传入时间与当前时间的天数
		int day = getStartDateAndEndDateIntervalDay(date, nowDate);
		String format = null;
		switch (day) {
			case -1:
				format = "后天HH:mm";
				break;
			case 0:
				format = "明天HH:mm";
				break;
			case 1:
				format = "HH:mm";
				break;
			case 2:
				format = "昨天HH:mm";
				break;
			case 3:
				format = "前天HH:mm";
				break;
			case 4:
				format = "三天前HH:mm";
				break;
			case 5:
				format = "四天前HH:mm";
				break;
			case 6:
				format = "五天前HH:mm";
				break;
			case 7:
				format = "六天前HH:mm";
				break;
			default:
				format = isOtherTime
						?
						(
							year==nowYear?"MM月dd日 HH:mm":"yyyy年MM月dd日 HH:mm"
						)
						:
						(
							year==nowYear?"MM月dd日":"yyyy年MM月dd日"
						);
				
				break;
		}
		return getDateFormatter(date, format);
	}

	/**
	 * 获取系统当期年月日（精确到天），格式：yyyyMMdd
	 * 
	 * @return 以yyyyMMdd为格式的当前系统时间为格式的当前系统年月日字符串
	 */
	public static String getDate() {
		return getDate(new Date());
	}

	/**
	 * 获取指定年月日（精确到天），格式：yyyyMMdd
	 * @param date 时间对象
	 * @return 以yyyyMMdd为格式的当前系统时间为格式的指定年月日字符串
	 */
	public static String getDate(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dtShort);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 获取系统当期年月日（精确到天），格式：yyyy-MM-dd
	 * 
	 * @return 以yyyy-MM-dd为格式的当前系统时间为格式的当前系统年月日字符串
	 */
	public static String getDates() {
		return getDates(new Date());
	}

	/**
	 * 获取指定年月日（精确到天），格式：yyyy-MM-dd
	 * @param date 时间对象
	 * @return 以yyyy-MM-dd为格式的当前系统时间为格式的指定年月日字符串
	 */
	public static String getDates(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(dtShorts);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 产生随机的三位数
	 * 
	 * @return
	 */
	public static String getThree() {
		return new Random().nextInt(1000) + "";
	}

	public static Date getStartTime() {
		return getStartTime(null);
	}

	public static Date getEndTime() {
		return getEndTime(null);
	}

	public static Date getStartTime(Date date) {
		Calendar todayStart = Calendar.getInstance(timeZone);
		if (date!=null) {
			todayStart.setTime(date);
		}
		todayStart.set(Calendar.HOUR_OF_DAY, 0);
		todayStart.set(Calendar.MINUTE, 0);
		todayStart.set(Calendar.SECOND, 0);
		todayStart.set(Calendar.MILLISECOND, 0);
		return todayStart.getTime();
	}

	public static Date getEndTime(Date date) {
		Calendar todayEnd = Calendar.getInstance(timeZone);
		if (date!=null) {
			todayEnd.setTime(date);
		}
		todayEnd.set(Calendar.HOUR_OF_DAY, 23);
		todayEnd.set(Calendar.MINUTE, 59);
		todayEnd.set(Calendar.SECOND, 59);
		todayEnd.set(Calendar.MILLISECOND, 999);
		return todayEnd.getTime();
	}

	/**
	 * 将时间对象转化为cronDate格式的cron表达式
	 * @param date 时间对象
	 * @return 以cronDate格式的cron表达式字符串
	 */
	public static String getCron(Date date) {
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(cronDate);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 获取系统当前日期（精确到秒），格式：yyyy-MM-dd HH:mm:ss
	 * @return 以yyyy-MM-dd HH:mm:ss为格式的当前系统时间为格式的当前系统年月日字符串
	 */
	public static String getDateFormatter() {
		return getDateFormatter(new Date());
	}

	/**
	 * 将时间对象转化为yyyy-MM-dd HH:mm:ss格式的时间字符串
	 * @param date 时间对象
	 * @return 以yyyy-MM-dd HH:mm:ss为格式的当前系统时间为格式的指定时间字符串
	 */
	public static String getDateFormatter(Date date) {
		if (date==null) {
			return null;
		}
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat(simple);
		simpleDateFormat.setTimeZone(timeZone);
		return simpleDateFormat.format(date);
	}

	/**
	 * 将时间对象转化为指定格式的时间字符串
	 * @param date 时间对象
	 * @param formatStr 时间格式
	 * @return 时间字符串
	 */
	public static String getDateFormatter(Date date, String formatStr) {
		if (date==null || StringUtils.isEmpty(formatStr)) {
			return null;
		} else {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatStr);
			simpleDateFormat.setTimeZone(timeZone);
			return simpleDateFormat.format(date);
		}
	}

	/**
	 * 将时间字符串或时间戳转为时间对象
	 * @param dateValue 时间数据
	 * @return 时间对象
	 * @throws Exception
	 */
	public static Date dateValueToDate(Object dateValue) throws Exception {
		if (dateValue==null) {
			return null;
		} else if (dateValue instanceof String) {
			return dateFormatStrToDate((String)dateValue);
		} else if (dateValue instanceof Byte) {
			return new Date((long)((byte)dateValue));
		} else if (dateValue instanceof Short) {
			return new Date((long)((short)dateValue));
		} else if (dateValue instanceof Integer) {
			return new Date((long)((int)dateValue));
		} else if (dateValue instanceof Long) {
			return new Date((long)dateValue);
		} else {
			throw new ClassCastException("不识别的时间类型："+dateValue.toString());
		}
	}

	/**
	 * 将“yyyy-MM-dd HH:mm:ss”格式的时间字符串转化为时间对象
	 * @param dateStr 时间字符串
	 * @return 时间对象
	 * @throws ParseException
	 */
	public static Date dateFormatStrToDate(String dateStr) 
			throws ParseException {
		if (StringUtils.isEmpty(dateStr)) {
			return null;
		} else {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(simple);
			simpleDateFormat.setTimeZone(timeZone);
			return simpleDateFormat.parse(dateStr);
		}
	}

	/**
	 * 将指定格式的时间字符串转化为时间对象
	 * @param dateStr 时间字符串
	 * @param formatStr 时间格式
	 * @return 时间对象
	 * @throws ParseException
	 */
	public static Date dateFormatStrToDate(String dateStr, String formatStr) 
			throws ParseException {
		if (StringUtils.isEmpty(dateStr) || StringUtils.isEmpty(formatStr) ) {
			return null;
		} else {
			SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatStr);
			simpleDateFormat.setTimeZone(timeZone);
			return simpleDateFormat.parse(dateStr);
		}
	}

	/**
	 * 获取当前时间指定天数后的时间
	 * @param day 正数为获取几天后的时间，负数为获取几天前的时间，0则直接返回传入的时间
	 * @return 时间对象
	 * @throws ParseException
	 */
	public static Date getAfterDayDate(int day) {
		return getAfterDayDate(new Date(), day);
	}

	/**
	 * 获取一个时间指定天数后的时间
	 * @param date 时间
	 * @param day 正数为获取几天后的时间，负数为获取几天前的时间，0则直接返回传入的时间
	 * @return 时间对象
	 * @throws ParseException
	 */
	public static Date getAfterDayDate(Date date, int day) {
		if (day==0) {
			return date;
		}
		Calendar calendar = Calendar.getInstance(timeZone);
		calendar.setTime(date);
		calendar.add(Calendar.DAY_OF_MONTH, day);
		return calendar.getTime();
	}

	/**
	 * 检查结束时间是否在开始时间之后
	 * @param startTime 开始时间
	 * @param endTime 结束时间
	 * @return true是    false否
	 */
	public static boolean checkEndTimeGreaterThanStartTime(Date startTime, Date endTime) {
		if (startTime==null || endTime==null) {
			return false;
		}
		if (endTime.getTime() > startTime.getTime()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 检查当前时间是否在开始时间和结束时间之间
	 * @param startTime 开始时间
	 * @param endTime 结束时间
	 * @return true是    false否
	 */
	public static boolean isNowTimeBetweenTheEndTimeAndStartTime(Date startTime, Date endTime) {
		//获取当前时间的时间戳（距离1970年1月1日0时0分0秒0毫秒的毫秒数）
		long nowTime = new Date().getTime();
		/*
			如果当前时间的时间戳大于或等于开始时间的时间戳
			并且当前时间的时间戳小于或等于结束时间的时间戳
			那么当前时间就在开始时间和结束时间之间
		*/
		if (nowTime>=startTime.getTime() && nowTime<=endTime.getTime()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 检查某个时间是否在当前时间后指定的时间段（毫秒数）
	 * @param time 判断的时间
	 * @param ms 指定的时间段（毫秒数）
	 * @return true是    false否
	 */
	public static boolean isNowTimeGreaterThanTimeByMs(Date time, long ms) {
		/*
			如果该时间的时间戳大于当前时间的时间戳加上指定的时间段（毫秒数）
			那么该时间就过了指定的时间段
			
			时间戳（距离1970年1月1日0时0分0秒0毫秒的毫秒数）
		*/
		if (time==null) {
			return false;
		} else if (time.getTime() > new Date().getTime()+ms) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 检查某个时间是否在当前时间指定天数后
	 * @param time 判断的时间
	 * @param day 自然天数
	 * @return true是    false否
	 */
	public static boolean isNowTimeGreaterThanTimeByDay(Date time, int day) {
		return isNowTimeGreaterThanTimeByMs(time, 86400000L*day);
	}

	/**
	 * 检查某个时间是否在当前时间指定天数后
	 * @param timeStr 判断的时间字符串
	 * @param formatStr 判断的时间格式
	 * @param day 自然天数
	 * @return true是    false否
	 * @throws ParseException 
	 */
	public static boolean isNowTimeGreaterThanTimeByDay(String timeStr, 
			String formatStr, int day) throws ParseException {
		return isNowTimeGreaterThanTimeByDay(dateFormatStrToDate(timeStr, formatStr), day);
	}

	/**
	 * 检查某个时间是否过了指定的毫秒数
	 * @param time 判断的时间
	 * @param ms 毫秒数
	 * @return true是    false否
	 */
	public static boolean isTimeGreaterThanNowTimeByMs(Date time, long ms) {
		if (time==null) {
			return false;
		} else if (time.getTime()+ms < new Date().getTime()) {
			return true;
		} else {
			return false;
		}
	}

	/**
	 * 检查某个时间是否过了指定的自然天数
	 * @param time 判断的时间
	 * @param day 自然天数
	 * @return true是    false否
	 */
	public static boolean isTimeGreaterThanNowTimeByDay(Date time, int day) {
		return isTimeGreaterThanNowTimeByMs(time, 86400000L*day);
	}

	/**
	 * 检查某个时间是否过了指定的自然天数
	 * @param timeStr 判断的时间字符串
	 * @param formatStr 判断的时间格式
	 * @param day 自然天数
	 * @return true是    false否
	 * @throws ParseException 
	 */
	public static boolean isTimeGreaterThanNowTimeByDay(String timeStr, 
			String formatStr, int day) throws ParseException {
		return isTimeGreaterThanNowTimeByDay(dateFormatStrToDate(timeStr, formatStr), day);
	}

	/**
	 * 得到开始时间与结束时间间隔的天数（不足24小时按一天计算）
	 * @param startDate 开始时间
	 * @param endDate 结束时间
	 * @return 间隔天数
	 */
	public static int getStartDateAndEndDateIntervalDay(Date startDate, Date endDate) {
		if (startDate==null || endDate==null) {
			return 0;
		}
		return (int) ((endDate.getTime()-startDate.getTime())/86400000L+1L);
	}

	/**
	 * 设置开始时间为当天00:00:00.000
	 * @param startDate 设置前的开始时间
	 * @return 设置后的开始时间
	 */
	public static Date setStartDate(Date startDate) {
		if (startDate==null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance(timeZone);
		calendar.setTime(startDate);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 设置结束时间为当天23:59:59.999
	 * @param startDate 设置前的结束时间
	 * @return 设置后的结束时间
	 */
	public static Date setEndDate(Date endDate) {
		if (endDate==null) {
			return null;
		}
		Calendar calendar = Calendar.getInstance(timeZone);
		calendar.setTime(endDate);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}

	/**
	 * 将时间字符串转换为开始时间 2018-10-01 00:00:00
	 * @param startDateStr 时间字符串
	 * @param formatStr 时间格式
	 * @return 转换后的开始时间
	 * @throws ParseException
	 */
	public static Date dateFormatStrToStartDate(String startDateStr, 
			String formatStr) throws ParseException {
		return setStartDate(dateFormatStrToDate(startDateStr, formatStr));
	}

	/**
	 * 将时间字符串转换为结束时间 2018-10-01 23:59:59
	 * @param endDateStr 时间字符串
	 * @param formatStr 时间格式
	 * @return 转换后的结束时间
	 * @throws ParseException
	 */
	public static Date dateFormatStrToEndDate(String EndDateStr, 
			String formatStr) throws ParseException {
		return setEndDate(dateFormatStrToDate(EndDateStr, formatStr));
	}

	/**
	 * 获取当年的第一天
	 * @return
	 */
	public static Date getCurrYearFirst(){
		return getYearFirst(null);
	}

	/**
	 * 获取当年的最后一天
	 * @return
	 */
	public static Date getCurrYearLast(){
		return getYearLast(null);
	}

	/**
	 * 获取某年第一天日期
	 * @param year 年份
	 * @return Date
	 */
	public static Date getYearFirst(Integer year){
		Calendar calendar = Calendar.getInstance(timeZone);
		if (year!=null) {
			calendar.set(Calendar.YEAR, year);
		}
		calendar.set(Calendar.DAY_OF_YEAR, 
				calendar.getActualMinimum(Calendar.DAY_OF_YEAR));
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取某年最后一天日期
	 * @param year 年份
	 * @return Date
	 */
	public static Date getYearLast(Integer year){
		Calendar calendar = Calendar.getInstance(timeZone);
		if (year!=null) {
			calendar.set(Calendar.YEAR, year);
		}
		calendar.set(Calendar.DAY_OF_YEAR, 
				calendar.getActualMaximum(Calendar.DAY_OF_YEAR));
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取当年当月的第一天
	 * @return
	 */
	public static Date getCurrMonthFirst(){
		return getMonthFirst(null, null);
	}

	/**
	 * 获取当年的最后一天
	 * @return
	 */
	public static Date getCurrMonthLast(){
		return getMonthLast(null, null);
	}

	/**
	 * 获取某年某月第一天日期
	 * @param year 年份
	 * @param month 月份
	 * @return Date
	 */
	public static Date getMonthFirst(Integer year, Integer month){
		Calendar calendar = Calendar.getInstance(timeZone);
		if (year!=null) {
			calendar.set(Calendar.YEAR, year);
		}
		if (month!=null) {
			calendar.set(Calendar.MONTH, month-1);
		}
		calendar.set(Calendar.DAY_OF_MONTH, 
				calendar.getActualMinimum(Calendar.DAY_OF_MONTH));
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取某年某月最后一天日期
	 * @param year 年份
	 * @param month 月份
	 * @return Date
	 */
	public static Date getMonthLast(Integer year, Integer month){
		Calendar calendar = Calendar.getInstance(timeZone);
		if (year!=null) {
			calendar.set(Calendar.YEAR, year);
		}
		if (month!=null) {
			calendar.set(Calendar.MONTH, month-1);
		}
		calendar.set(Calendar.DAY_OF_MONTH, 
				calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 将当前日期设置到指定的时间
	 * @param time 指定时间
	 * @return
	 */
	public static Date setNowDateTime(Date time) {
		return setThisDateTime(null, time);
	}

	/**
	 * 将指定日期设置到指定的时间
	 * @param thisDate 指定日期（为null时默认为当前日期）
	 * @param time 指定时间
	 * @return
	 */
	public static Date setThisDateTime(Date thisDate, Date time) {
		if (time==null) {
			return null;
		}
		if (thisDate==null) {
			thisDate = new Date();
		}
		//日期
		Calendar thisCalendar = Calendar.getInstance(timeZone);
		thisCalendar.setTime(thisDate);
		//时间
		Calendar timeCalendar = Calendar.getInstance(timeZone);
		timeCalendar.setTime(time);
		timeCalendar.set(Calendar.YEAR, thisCalendar.get(Calendar.YEAR));
		timeCalendar.set(Calendar.MONTH, thisCalendar.get(Calendar.MONTH));
		timeCalendar.set(Calendar.DATE, thisCalendar.get(Calendar.DATE));
		return timeCalendar.getTime();
	}

	/**
	 * 算出两个时间相差的值
	 * @param comparisonDate 比较时间
	 * @param referenceDate 参考时间
	 * @param unit 单位（1毫秒，2秒，3分钟，4小时，5天，6周）
	 * @return 相差的值（正数表示比较时间在参考时间之后，负数表示比较时间在参考时间之前，零表示比较时间与参考时间相同）
	 */
	public static long afterDate(Date comparisonDate, Date referenceDate, int unit) {
		if (comparisonDate==null || referenceDate==null) {
			return 0;
		}
		switch (unit) {
			case 1:
				return comparisonDate.getTime()-referenceDate.getTime();
			case 2:
				return (comparisonDate.getTime()-referenceDate.getTime())/1000L;
			case 3:
				return (comparisonDate.getTime()-referenceDate.getTime())/60000L;
			case 4:
				return (comparisonDate.getTime()-referenceDate.getTime())/3600000L;
			case 5:
				return (comparisonDate.getTime()-referenceDate.getTime())/86400000L;
			case 6:
				return (comparisonDate.getTime()-referenceDate.getTime())/604800000L;
			default:
				return 0;
		}
	}

	/**
	 * 获取包含时间单位的字符串
	 * @param times 数值
	 * @param unitType 单位类型（1天，2小时，3分钟，4秒，5毫秒）
	 * @return
	 */
	public static String getUnitTime(long times, int unitType) {
		String unitTime = null;
		long days = 0;//天
		long hours = 0;//小时
		long minutes = 0;//分钟
		long seconds = 0;//秒
		long milliseconds = 0;//毫秒
		switch (unitType) {
			case 1://天
				unitTime = times+"天";
				break;
			case 2://小时
				hours = times%60;
				unitTime = (days>0?days+"天":"")+hours+"小时";
				break;
			case 3://分钟
				minutes = times%60;
				hours = times/60;
				days = hours/24;
				hours %= 24;
				unitTime = (days>0?days+"天":"")+(hours>0?hours+"小时":"")+minutes+"分钟";
				break;
			case 4://秒
				seconds = times%60;
				minutes = times/60;
				hours = minutes/60;
				minutes %= 60;
				days = hours/24;
				hours %= 24;
				unitTime = (days>0?days+"天":"")+(hours>0?hours+"小时":"")
						+(minutes>0?minutes+"分钟":"")+(seconds>0?seconds+"秒":"");
				break;
			case 5://毫秒
				milliseconds = times%1000;
				seconds = times/1000;
				minutes = seconds/60;
				seconds %= 60;
				hours = minutes/60;
				minutes %= 60;
				days = hours/24;
				hours %= 24;
				unitTime = (days>0?days+"天":"")+(hours>0?hours+"小时":"")
						+(minutes>0?minutes+"分钟":"")+(seconds>0?seconds+"秒":"")
						+(milliseconds>0?milliseconds+"毫秒":"");
				break;
			default:
				break;
		}
		return unitTime;
	}

	/**
	 * 根据天数获取包含时间单位的字符串
	 * @param days 天数
	 * @return
	 */
	public static String getUnitTimeByDays(long days) {
		return getUnitTime(days, 1);
	}

	/**
	 * 根据小时数获取包含时间单位的字符串
	 * @param hours 小时数
	 * @return
	 */
	public static String getUnitTimeByHours(long hours) {
		return getUnitTime(hours, 2);
	}

	/**
	 * 根据分钟数获取包含时间单位的字符串
	 * @param minutes 分钟数
	 * @return
	 */
	public static String getUnitTimeByMinutes(long minutes) {
		return getUnitTime(minutes, 3);
	}

	/**
	 * 根据秒数获取包含时间单位的字符串
	 * @param seconds 秒数
	 * @return
	 */
	public static String getUnitTimeBySeconds(long seconds) {
		return getUnitTime(seconds, 4);
	}

	/**
	 * 根据毫秒数获取包含时间单位的字符串
	 * @param milliseconds 毫秒数
	 * @return
	 */
	public static String getUnitTimeByMilliseconds(long milliseconds) {
		return getUnitTime(milliseconds, 5);
	}

	/**
	 * 获取当前时间的年份
	 * @return 年份
	 */
	public static int getYear() {
		return getYear(null);
	}

	/**
	 * 获取指定时间的年份
	 * @param date 时间对象
	 * @return 年份
	 */
	public static int getYear(Date date) {
		return getDateProperty(date, 1);
	}

	/**
	 * 获取当前时间的月份
	 * @return 月份[1,12]
	 */
	public static int getMonth() {
		return getMonth(null);
	}

	/**
	 * 获取指定时间的月份
	 * @param date 时间对象
	 * @return 月份[1,12]
	 */
	public static int getMonth(Date date) {
		return getDateProperty(date, 2);
	}

	/**
	 * 获取当前时间的日
	 * @return 日[1,31]
	 */
	public static int getDay() {
		return getDay(null);
	}

	/**
	 * 获取指定时间的日
	 * @param date 时间对象
	 * @return 日[1,31]
	 */
	public static int getDay(Date date) {
		return getDateProperty(date, 3);
	}

	/**
	 * 获取当前时间的时
	 * @return 时[0,23]
	 */
	public static int getHour() {
		return getHour(null);
	}

	/**
	 * 获取指定时间的时
	 * @param date 时间对象
	 * @return 时[0,23]
	 */
	public static int getHour(Date date) {
		return getDateProperty(date, 4);
	}

	/**
	 * 获取当前时间的分
	 * @return 分[0,59]
	 */
	public static int getMinute() {
		return getMinute(null);
	}

	/**
	 * 获取指定时间的分
	 * @param date 时间对象
	 * @return 分[0,59]
	 */
	public static int getMinute(Date date) {
		return getDateProperty(date, 5);
	}

	/**
	 * 获取当前时间的秒
	 * @return 秒[0,59]
	 */
	public static int getSecond() {
		return getSecond(null);
	}

	/**
	 * 获取指定时间的秒
	 * @param date 时间对象
	 * @return 秒[0,59]
	 */
	public static int getSecond(Date date) {
		return getDateProperty(date, 6);
	}

	/**
	 * 获取当前时间的毫秒
	 * @return 毫秒[0,999]
	 */
	public static int getMilliSecond() {
		return getMilliSecond(null);
	}

	/**
	 * 获取指定时间的毫秒
	 * @param date 时间对象
	 * @return 毫秒[0,999]
	 */
	public static int getMilliSecond(Date date) {
		return getDateProperty(date, 7);
	}

	/**
	 * 获取当前日期是星期几
	 * @param date 时间对象
	 * @return 当前日期是星期几
	 */
	public static String getDateWeek(Date date) {
		String[] weekDays = {
			"星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"
		};
		Calendar calendar = Calendar.getInstance(timeZone);
		if (date!=null) {
			calendar.setTime(date);
		}
		int weekIndex = calendar.get(Calendar.DAY_OF_WEEK) - 1;
		if (weekIndex < 0) {
			weekIndex = 0;
		} else if (weekIndex > 6) {
			weekIndex = 6;
		}
		return weekDays[weekIndex];
	}

	/**
	 * 获取当前时间的属性
	 * @param type 获取类型（1年份，2月份，3日，4时，5分，6秒，7毫秒，8本年第一天，9本年最后一天，
	 *                    10本年本月第一天，11本年本月最后一天，12本年第一月，13本年最后一月）
	 * @return 属性值
	 */
	public static int getDateProperty(int type) {
		return getDateProperty(null, type);
	}

	/**
	 * 获取指定时间的属性
	 * @param date 时间对象
	 * @param type 获取类型（1年份，2月份，3日，4时，5分，6秒，7毫秒，8本年第一天，9本年最后一天，
	 *                    10本年本月第一天，11本年本月最后一天，12本年第一月，13本年最后一月，14星期）
	 * @return 属性值
	 */
	public static int getDateProperty(Date date, int type) {
		Calendar calendar = Calendar.getInstance(timeZone);
		if (date!=null) {
			calendar.setTime(date);
		}
		switch (type) {
			case 1://年份
				return calendar.get(Calendar.YEAR);
			case 2://月份
				return calendar.get(Calendar.MONTH)+1;
			case 3://日
				return calendar.get(Calendar.DATE);
			case 4://时
				return calendar.get(Calendar.HOUR_OF_DAY);
			case 5://分
				return calendar.get(Calendar.MINUTE);
			case 6://秒
				return calendar.get(Calendar.SECOND);
			case 7://毫秒
				return calendar.get(Calendar.MILLISECOND);
			case 8://本年第一天
				return calendar.getActualMinimum(Calendar.DAY_OF_YEAR);
			case 9://本年最后一天
				return calendar.getActualMaximum(Calendar.DAY_OF_YEAR);
			case 10://本年本月第一天
				return calendar.getActualMinimum(Calendar.DAY_OF_MONTH);
			case 11://本年本月最后一天
				return calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
			case 12://本年第一月
				return calendar.getActualMinimum(Calendar.MONTH)+1;
			case 13://本年最后一月
				return calendar.getActualMaximum(Calendar.MONTH)+1;
			case 14://星期
				return calendar.get(Calendar.DAY_OF_WEEK);
			default:
				return 0;
		}
	}

	/**
	 * 将年月日时分秒毫秒组成时间对象
	 * @param year 年
	 * @param month 月
	 * @param day 日
	 * @param hour 时
	 * @param minute 分
	 * @param second 秒
	 * @param milliSecond 毫秒
	 * @return
	 */
	public static Date getDate(Integer year, Integer month, Integer day, 
			Integer hour, Integer minute, Integer second, Integer milliSecond) {
		return getDate(null, year, month, day, hour, minute, second, milliSecond);
	}

	/**
	 * 将年月日时分秒毫秒组成时间对象
	 * @param date 时间对象
	 * @param year 年
	 * @param month 月
	 * @param day 日
	 * @param hour 时
	 * @param minute 分
	 * @param second 秒
	 * @param milliSecond 毫秒
	 * @return
	 */
	public static Date getDate(Date date, Integer year, Integer month, Integer day, 
			Integer hour, Integer minute, Integer second, Integer milliSecond) {
		Calendar calendar = Calendar.getInstance(timeZone);
		if (date!=null) {
			calendar.setTime(date);
		}
		if (year!=null) {
			calendar.set(Calendar.YEAR, year);
		}
		if (month!=null) {
			calendar.set(Calendar.MONTH, month-1);
		}
		if (day!=null) {
			calendar.set(Calendar.DATE, day);
		}
		if (hour!=null) {
			calendar.set(Calendar.HOUR_OF_DAY, hour);
		}
		if (minute!=null) {
			calendar.set(Calendar.MINUTE, minute);
		}
		if (second!=null) {
			calendar.set(Calendar.SECOND, second);
		}
		if (milliSecond!=null) {
			calendar.set(Calendar.MILLISECOND, milliSecond);
		}
		return date;
	}

	/**
	 * 根据生日获取年龄
	 * @param birthDay 生日
	 * @return
	 */
	public static int getAge(Date birthday) {
		if (birthday==null) {
			return 0;
		}
		Calendar calendar = Calendar.getInstance(timeZone);
		
		int yearNow = calendar.get(Calendar.YEAR);
		int monthNow = calendar.get(Calendar.MONTH);
		int dayOfMonthNow = calendar.get(Calendar.DAY_OF_MONTH);
		
		calendar.setTime(birthday);
		
		int yearBirth = calendar.get(Calendar.YEAR);
		int monthBirth = calendar.get(Calendar.MONTH);
		int dayOfMonthBirth = calendar.get(Calendar.DAY_OF_MONTH);
		
		int age = yearNow - yearBirth;
		
		if (monthNow <= monthBirth) {
			if (monthNow == monthBirth) {
				if (dayOfMonthNow < dayOfMonthBirth) age--;
			} else {
				age--;
			}
		}
		return age;
	}

	/**
	 * 获取起止日期之间的所有日期字符串
	 * @param startDate 开始日期
	 * @param endDate 结束日期
	 * @return
	 */
	public static List<String> getBetweenStartAndEndDayStrings(Date startDate, Date endDate) {
		List<Date> dayDates = getBetweenStartAndEndDayDates(startDate, endDate);
		if (dayDates==null) {
			return null;
		}
		List<String> dayStrings = new ArrayList<String>();
		for (Date dayDate : dayDates) {
			dayStrings.add(getDateFormatter(dayDate, dtShorts));
		}
		return dayStrings;
	}

	/**
	 * 获取起止日期之间的所有日期对象
	 * @param startDate 开始日期
	 * @param endDate 结束日期
	 * @return
	 */
	public static List<Date> getBetweenStartAndEndDayDates(Date startDate, Date endDate) {
		if (startDate==null || endDate==null) {
			return null;
		}
		startDate = setStartDate(startDate);
		endDate = setStartDate(endDate);
		if (startDate.getTime()>endDate.getTime()) {
			return null;
		}
		List<Date> dayDates = new ArrayList<Date>();
		Calendar calendar = Calendar.getInstance(timeZone);
		Date date = startDate;
		do {
			dayDates.add(date);
			calendar.setTime(date);
			calendar.add(Calendar.DATE, 1);
			date = calendar.getTime();
		} while (date.getTime()<=endDate.getTime());
		return dayDates;
	}

	/**
	 * 获取某个时间段内所有月份
     * @param startDate 开始时间
     * @param endDate 结束时间
     * @return 日期集合 格式为 年-月-日 每个月第一天的日期
     * @throws Exception
     */
	public static List<String> getMonthBetween(Date startDate, Date endDate) {
		List<String> result = new ArrayList<String>();
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月
		Calendar min = Calendar.getInstance();
		Calendar max = Calendar.getInstance();
		
		min.setTime(startDate);
		min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);
		
		max.setTime(endDate);
		max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);
		
		Calendar curr = min;
		while (curr.before(max)) {
			result.add(sdf.format(curr.getTime()));
			curr.add(Calendar.MONTH, 1);
		}
		return result;
	}

	/**
	 * 获取日期的其他月份的日期
	 * @param date 日期对象
	 * @param type 类型（-2上上个月，-1上个月，0本月，1下个月，2下下个月）
	 * @return
	 */
	public static Date getMonthPrev(Date date, int type){
		Calendar calendar = Calendar.getInstance(timeZone);//得到一个Calendar的实例 
		if (date!=null) {
			calendar.setTime(date); //设置时间为当前时间 
		}
		if (type!=0) {
			calendar.add(Calendar.MONTH, type);
		}
		return calendar.getTime();
	}

	/**
    * 获取当前日期的上个月的日期
    */
	public static Date getMonthPrev(){
		return getMonthPrev(null, -1);
	}

	/**
	 * 获取当前日期的上上个月的日期
	 */
	public static Date getMonthPrevs(){
		return getMonthPrev(null, -2);
	}
}
